home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d1 / freemacs.arc / MARKS.ASM < prev    next >
Assembly Source File  |  1988-03-17  |  14KB  |  606 lines

  1. ;History:560,23301,1
  2.     .xlist
  3.     page    ,132
  4.  
  5.     include    memory.def
  6.     include    mintdefs.asm
  7.  
  8. data    segment    byte public
  9.     extrn    syntax_table: word
  10.     extrn    textseg: word
  11.  
  12. ;Marks are referred to by a single ASCII character.  If the mark is a digit,
  13. ;  it is a user-defined mark.
  14. mark_first_temp    equ    '0'    ;first temp mark
  15. mark_last_temp    equ    '9'    ;last temp mark
  16. mark_first_perm    equ    '@'    ;first permanent mark.
  17. mark_last_perm    equ    'Z'    ;last permanent mark.
  18. mark_split    equ    '*'    ;split mark
  19.  
  20. ;If the mark is one of the following characters, it is a system-defined mark.
  21. mark_list    label    byte
  22.     db    '>'        ;character to the right of the point
  23.     dw    mark_right
  24.     db    '<'        ;character to the left of the point.
  25.     dw    mark_left
  26.     db    '['        ;first character in the file.
  27.     dw    mark_top
  28.     db    ']'        ;last character in the file.
  29.     dw    mark_bot
  30.     db    '^'        ;beginning of this line.
  31.     dw    mark_begin
  32.     db    '$'        ;end of this line.
  33.     dw    mark_end
  34.     db    '-'        ;blanks to the left.
  35.     dw    mark_lblanks
  36.     db    '+'        ;blanks to the right.
  37.     dw    mark_rblanks
  38.     db    '}'        ;word to the right of this one.
  39.     dw    mark_word_right
  40.     db    '{'        ;word to the left of this one.
  41.     dw    mark_word_left
  42.     db    '.'        ;point or anything else no in the list.
  43.     dw    mark_point
  44. mark_list_size    equ    ($-mark_list)/3
  45.  
  46.  
  47. data    ends
  48.  
  49.  
  50. bufseg    segment    public
  51.  
  52. byte_ptr    label    byte
  53.  
  54.     extrn    toptop: word
  55.     extrn    topbot: word
  56.     extrn    bottop: word
  57.     extrn    botbot: word
  58.  
  59. comment /*******************************************************************
  60.     marks contains the marks, which is a count of characters from the
  61. beginning of the file.  There are permanent (global) marks and temporary
  62. (local) marks.  The permanent marks are accessible at all times, while the
  63. temporary marks are accessible only while they are on the top of the stack.
  64. There are a These marks are defined below.  The actual number of temporary
  65. marks is given by the value of [temp_mark_count]-[temp_mark_base].  As you can
  66. see, this is initially zero.  The number of marks is adjusted by calling
  67. stack_marks.
  68. ****************************************************************************/
  69.  
  70. MAX_MARKS    equ    50
  71. temp_mark_base    db    ?        ;first temporary mark
  72. temp_mark_count    db    ?        ;total number of temporary marks
  73. perm_mark_count    db    ?        ;number of permanent marks
  74.     public    split_mark
  75. split_mark    dw    ?        ;mark used for split screen.
  76. mark_offset    dw    max_marks dup(?)
  77. marks_sp    dw    ?
  78.     db    max_marks dup(?)
  79.  
  80. wdummy    struc
  81. w    dw    ?
  82. wdummy    ends
  83.  
  84. bdummy    struc
  85. b    db    ?
  86. bdummy    ends
  87.  
  88. bufseg    ends
  89.  
  90.  
  91. code    segment    byte public
  92.     assume    cs:code, ds:data, es:data
  93.  
  94.     public    set_mark
  95. set_mark:
  96.     push    ds
  97.     mov    ds,textseg
  98.     call    set_mark$
  99.     pop    ds
  100.     ret
  101.  
  102.  
  103.     public    stack_marks
  104. stack_marks:
  105.     push    ds
  106.     mov    ds,textseg
  107.     call    stack_marks$
  108.     pop    ds
  109.     ret
  110.  
  111. code    ends
  112.  
  113. code    segment    byte public
  114.     assume    cs:code, ds:bufseg, es:data
  115.  
  116.     public    init_marks
  117.     public    set_mark_si
  118.     public    get_mark
  119.     public    adjust_marks_del
  120.     public    adjust_marks_ins
  121.  
  122.  
  123. init_marks:
  124.     mov    temp_mark_base,1
  125.     mov    temp_mark_count,1
  126.     mov    perm_mark_count,1
  127.     mov    bx,offset marks_sp+2
  128.     mov    byte ptr [bx],0        ;initial stack frame is empty.
  129.     mov    marks_sp,bx
  130.     mov    mark_offset[0],0    ;init the only mark.
  131.     mov    split_mark,0        ;set the mark to the beginning.
  132.     ret
  133.  
  134.  
  135. user_mark:
  136. ;enter with al=mark.
  137. ;if user mark, exit with bx->proper marks array entry, nc.
  138. ;if sytem mark, exit with cy.
  139.     cmp    al,mark_first_perm    ;permanent user mark?
  140.     jb    user_mark_3
  141.     cmp    al,mark_last_perm
  142.     ja    user_mark_3
  143.     mov    bl,al
  144.     sub    bl,mark_first_perm
  145.     cmp    bl,perm_mark_count
  146.     jae    user_mark_1        ;too bit, can't be user mark.
  147.     jmp    short user_mark_2
  148. user_mark_3:
  149.     cmp    al,mark_first_temp
  150.     jb    user_mark_1
  151.     cmp    al,mark_last_temp
  152.     ja    user_mark_1
  153.     mov    bl,al
  154.     sub    bl,mark_first_temp
  155.     mov    bh,temp_mark_count    ;compute the number of temporary marks.
  156.     sub    bh,temp_mark_base
  157.     cmp    bl,bh
  158.     jae    user_mark_1        ;too big, can't be user mark.
  159.     add    bl,temp_mark_base
  160. user_mark_2:
  161.     add    bl,bl
  162.     mov    bh,0
  163.     lea    bx,mark_offset[bx]
  164.     ret                ;cy was cleared by previous operation
  165. user_mark_1:
  166.     cmp    al,mark_split        ;split is a settable mark.
  167.     jne    user_mark_4
  168.     mov    bx,offset split_mark
  169.     ret
  170. user_mark_4:
  171.     stc
  172.     ret
  173.  
  174.  
  175. stack_marks$:
  176. ;enter with ax>0=number of temporary marks to stack or
  177. ;  ax<0=number of permanent marks to create (temporary marks are destroyed) or
  178. ;  ax=0 to unstack.
  179. ;exit with cy if overflow/underflow.
  180.     cmp    ax,0
  181.     jg    stack_marks_1    ;stack
  182.     jl    stack_marks_4    ;create perms.
  183.     mov    bx,marks_sp
  184.     mov    al,[bx]        ;get the current frame size
  185.     or    al,al
  186.     je    stack_marks_2    ;nothing to unstack.
  187.     sub    temp_mark_count,al    ;reduce count by this frame size
  188.     dec    bx
  189.     mov    al,[bx]        ;get the previous frame size
  190.     sub    temp_mark_base,al
  191.     mov    marks_sp,bx
  192.     clc
  193.     ret
  194. stack_marks_4:
  195.     neg    ax
  196.     cmp    al,MAX_MARKS        ;stack overflow?
  197.     jae    stack_marks_2        ;  yes.
  198.     mov    temp_mark_base,al
  199.     mov    temp_mark_count,al
  200.     mov    perm_mark_count,al
  201.     mov    bx,offset marks_sp    ;find the new tos.
  202.     add    bx,ax
  203.     mov    byte ptr [bx],0        ;initial stack frame is empty.
  204.     mov    marks_sp,bx
  205.     mov    ax,'.'*256+mark_first_perm
  206.     mov    cl,perm_mark_count
  207.     mov    ch,0
  208.     jmp    short stack_marks_3
  209. stack_marks_1:
  210.     mov    ah,temp_mark_count    ;get number of marks.
  211.     add    ah,al            ;add desired number
  212.     cmp    ah,MAX_MARKS        ;stack overflow?
  213.     jae    stack_marks_2        ;  yes.
  214.     mov    bx,marks_sp
  215.     inc    bx            ;bump stack pointer
  216.     mov    [bx],al            ;save the frame size
  217.     mov    marks_sp,bx
  218.     mov    al,temp_mark_count
  219.     mov    temp_mark_base,al    ;new base is old max.
  220.     mov    temp_mark_count,ah    ;new max is old+count of new marks
  221. ;set all the new temp marks to the point.
  222.     sub    ah,al            ;ah=temp_mark_count-temp_mark_base
  223.     mov    cl,ah
  224.     mov    ch,0
  225.     mov    ax,'.'*256+mark_first_temp
  226. stack_marks_3:
  227.     push    ax
  228.     push    cx
  229.     call    set_mark$
  230.     pop    cx
  231.     pop    ax
  232.     inc    al
  233.     loop    stack_marks_3
  234.     clc
  235.     ret
  236. stack_marks_2:
  237.     stc
  238.     ret
  239.  
  240.  
  241. set_mark_si:
  242. ;enter with al=number of dest mark, si->text.
  243. ;note that system marks cannot be set.
  244.     call    user_mark
  245.     jc    set_mark_si_1    ;not a user mark.
  246.     cmp    si,topbot    ;is new mark above point?
  247.     jb    set_mark_si_2    ;no, make it relative to toptop
  248.     sub    si,bottop
  249.     add    si,topbot
  250.     sub    si,toptop
  251.     jmp    short set_mark_si_3
  252. set_mark_si_2:
  253.     sub    si,toptop
  254. set_mark_si_3:
  255.     mov    [bx],si
  256. set_mark_si_1:
  257.     ret
  258.  
  259.  
  260. set_mark$:
  261. ;enter with al=dest mark, ah=source mark.
  262.     push    ax
  263.     mov    al,ah
  264.     call    get_mark_count
  265.     pop    ax
  266.     call    user_mark
  267.     jc    set_mark_1
  268.     mov    [bx],cx        ;store the mark.
  269. set_mark_1:
  270.     ret
  271.  
  272.  
  273.     assume    es:nothing, ss:data
  274.  
  275. get_mark_count:
  276. ;enter with al=number of mark to get.
  277. ;exit with cx=number of characters before the mark.
  278.     call    user_mark
  279.     jc    get_mark_count_1    ;anything larger (or negative)
  280.     mov    cx,[bx]
  281.     ret
  282. get_mark_count_1:
  283.     mov    bx,offset mark_list-3    ;get the mark list.
  284.     mov    cx,mark_list_size
  285. get_mark_count_2:            ;scan the list for the mark.
  286.     add    bx,3            ;preincrement
  287.     cmp    al,ss:[bx]        ;is it this one?
  288.     loopne    get_mark_count_2    ;continue if not.
  289.     jmp    word ptr ss:[bx+1]    ;go to the correct mark.
  290.  
  291.  
  292. mark_right:
  293.     mov    cx,botbot    ;compute the number of characters after the
  294.     sub    cx,bottop    ;  point.
  295.     je    mark_bot    ;  return the mark at the end of the file.
  296.     mov    cx,topbot    ;compute the number of characters before the
  297.     sub    cx,toptop    ;  point.
  298.     inc    cx        ;because we want the character to the right.
  299.     mov    bx,bottop    ;check for breaking up a NEWLINE
  300.     cmp    [bx].w,LINENEW
  301.     jne    mark_right_1    ;not NEWLINE.
  302.     inc    cx        ;because we don't want to split a newline.
  303. mark_right_1:
  304.     ret
  305.  
  306.  
  307. mark_left:
  308.     mov    cx,topbot
  309.     sub    cx,toptop
  310.     jz    mark_left_1    ;if no characters, mark is at beginning of file.
  311.     dec    cx        ;because we want the character to the left.
  312.     mov    bx,topbot
  313.     cmp    [bx-2].w,LINENEW
  314.     jne    mark_left_1
  315.     dec    cx        ;because we don't want to split a newline.
  316. mark_left_1:
  317.     ret
  318.  
  319.  
  320. mark_top:
  321.     mov    cx,0        ;zero characters before beginning of file.
  322.     ret
  323.  
  324.  
  325. mark_bot:
  326.     mov    cx,topbot    ;size of text before point +
  327.     sub    cx,toptop
  328.     add    cx,botbot    ;size of text after point.
  329.     sub    cx,bottop
  330.     ret
  331.  
  332.  
  333. mark_point:
  334.     mov    cx,topbot    ;size of text before point.
  335.     sub    cx,toptop
  336.     ret
  337.  
  338.  
  339. mark_begin:
  340.     mov    cx,topbot
  341.     mov    bx,cx
  342.     sub    cx,toptop
  343. mark_begin_1:
  344.     cmp    [bx-2].w,LINENEW    ;at beginning?
  345.     je    mark_begin_2        ;yes.
  346.     dec    bx
  347.     dec    cx
  348.     jmp    mark_begin_1
  349. mark_begin_2:
  350.     ret
  351.  
  352.  
  353. mark_end:
  354.     mov    cx,topbot        ;start at point
  355.     sub    cx,toptop
  356.     mov    bx,bottop
  357. mark_end_1:
  358.     cmp    [bx].w,LINENEW    ;at end?
  359.     je    mark_end_2    ;yes.
  360.     inc    bx
  361.     inc    cx
  362.     jmp    mark_end_1
  363. mark_end_2:
  364.     ret
  365.  
  366.  
  367. mark_word_right:
  368.     mov    cx,topbot        ;start at point
  369.     sub    cx,toptop
  370.     mov    bx,bottop
  371. mark_word_right_1:
  372.     cmp    bx,botbot        ;end of buffer is end of word.
  373.     je    mark_word_right_2
  374.     mov    al,[bx]            ;is this character a blank?
  375.     call    get_syntax
  376.     test    al,1
  377.     je    mark_word_right_2    ;yes - we're done.
  378.     inc    bx
  379.     inc    cx
  380.     jmp    mark_word_right_1
  381. mark_word_right_2:
  382.     ret
  383.  
  384.  
  385. mark_word_left:
  386.     mov    cx,topbot        ;start at point
  387.     mov    bx,cx
  388.     sub    cx,toptop
  389.     jcxz    mark_word_left_1    ;if nothing to the left, leave.
  390.     dec    bx
  391. mark_word_left_2:
  392.     mov    al,[bx]            ;is this character a blank?
  393.     call    get_syntax
  394.     test    al,1
  395.     je    mark_word_left_1    ;yes - exit now.
  396.     dec    bx
  397.     dec    cx
  398.     jne    mark_word_left_2
  399. mark_word_left_1:
  400.     ret
  401.  
  402.  
  403. mark_lblanks:
  404.     mov    cx,topbot        ;start at point
  405.     mov    bx,cx
  406.     sub    cx,toptop
  407.     jcxz    mark_lblanks_1        ;if nothing to left, leave.
  408.     dec    bx
  409.     cmp    [bx-1].w,LINENEW    ;starting at newline?
  410.     jne    mark_lblanks_2        ;no.
  411.     sub    cx,2            ;yes - move back over it.
  412.     sub    bx,2
  413.     jcxz    mark_lblanks_1        ;if nothing more to left, leave.
  414. mark_lblanks_2:
  415.     mov    al,[bx]            ;is this char a blank?
  416.     call    get_syntax
  417.     test    al,3            ;non-blank or line break?
  418.     jne    mark_lblanks_1    ;yes - exit now.
  419.     dec    bx
  420.     dec    cx
  421.     jne    mark_lblanks_2
  422. mark_lblanks_1:
  423.     ret
  424.  
  425.  
  426. mark_rblanks:
  427.     mov    cx,topbot        ;start at point
  428.     sub    cx,toptop
  429.     mov    bx,bottop
  430.     cmp    [bx].w,LINENEW        ;starting at newline?
  431.     jne    mark_rblanks_1        ;no.
  432.     cmp    bx,botbot        ;starting at end of buffer?
  433.     je    mark_rblanks_2        ;yes - end.
  434.     add    bx,2            ;start by skipping the newline.
  435.     add    cx,2
  436. mark_rblanks_1:
  437.     cmp    bx,botbot        ;end of buffer is end of word.
  438.     je    mark_rblanks_2        ;yes - end.
  439.     mov    al,[bx]
  440.     call    get_syntax
  441.     test    al,3            ;non-blank or line break?
  442.     jne    mark_rblanks_2        ;yes - exit now.
  443.     inc    bx
  444.     inc    cx
  445.     jmp    mark_rblanks_1
  446. mark_rblanks_2:
  447.     ret
  448.  
  449.  
  450.     public    split_at_point
  451. split_at_point:
  452. ;return cy if the split mark is at or after the point.
  453.     mov    cx,split_mark
  454.     mov    ax,topbot
  455.     sub    ax,toptop
  456.     cmp    split_mark,ax        ;is the split mark at or after the point?
  457.     jae    split_at_point_1    ;yes - return cy.
  458.     clc
  459.     ret
  460. split_at_point_1:
  461.     stc
  462.     ret
  463.  
  464.  
  465.     public    get_split_mark
  466. get_split_mark:
  467. ;same as get_mark('*'), only faster.
  468.     mov    cx,split_mark
  469.     jmp    short compute_mark
  470. get_mark:
  471. ;enter with al=number of mark to get.
  472.     call    get_mark_count
  473. compute_mark:
  474. ;enter with cx=the number of characters before the point.
  475. ;exit with cx=count of chars between the mark and the point, si->text at mark,
  476. ;cy=1 if mark is after the point.
  477.     mov    si,topbot
  478.     sub    si,toptop
  479.     sub    cx,si
  480.     jb    compute_mark_1
  481.     mov    si,bottop    ;make si->bottom
  482.     add    si,cx        ;make si->text.
  483.     stc
  484.     ret
  485. compute_mark_1:
  486.     mov    si,topbot    ;Compute pointer to text.
  487.     add    si,cx        ;  cx is difference between topbot and mark,
  488.     neg    cx        ;  which is negative.  make it positive.
  489.     clc
  490.     ret
  491.  
  492.  
  493.     assume    es:data
  494.  
  495.  
  496. adjust_marks_ins:
  497. ;enter with ax=number of characters inserted
  498. ;exit with all marks adjusted accordingly.
  499. ;if a mark is at or after the point, move it up or down.
  500. ;if a mark is before the point, leave it alone.
  501.     mov    cl,temp_mark_count
  502.     mov    ch,0
  503.     inc    cx
  504.     mov    bx,offset mark_offset-2
  505.     mov    dx,topbot
  506.     sub    dx,toptop
  507. adjust_marks_ins_1:
  508.     mov    si,[bx]            ;get a mark
  509.     cmp    si,dx            ;is it before the point?
  510.     jb    adjust_marks_ins_2    ;yes.
  511. adjust_marks_ins_3:
  512.     add    si,ax            ;no - adjust it and store it back.
  513.     mov    [bx],si
  514. adjust_marks_ins_2:
  515.     add    bx,2            ;go to the next mark.
  516.     loop    adjust_marks_ins_1
  517.     ret
  518.  
  519.  
  520. adjust_marks_del:
  521. ;enter with ax=number of characters deleted.
  522. ;exit with all marks adjusted accordingly.
  523. ;if a mark is after the point, move it up or down.
  524. ;if a mark is at or before the point, leave it alone.
  525. ;Adjusting for deletion is more complex than adjusting for insertion,
  526. ;  because we have to adjust all the marks that fall in the range of
  527. ;  the characters deleted.
  528.     mov    cl,temp_mark_count
  529.     mov    ch,0
  530.     inc    cx
  531.     mov    bx,offset mark_offset-2
  532.     mov    dx,topbot
  533.     sub    dx,toptop        ;make dx -> before first mark to adjust
  534.     mov    di,dx
  535.     add    di,ax            ;make di -> last mark to adjust.
  536. adjust_marks_del_1:
  537.     mov    si,[bx]            ;get a mark
  538.     cmp    si,dx            ;is it at or before the point?
  539.     jbe    adjust_marks_del_2    ;yes.
  540.     cmp    si,di            ;does it mark a deleted character?
  541.     ja    adjust_marks_del_3    ;no - adjust it down.
  542.     mov    [bx],dx            ;all deleted marks will mark the point.
  543.     jmp    short adjust_marks_del_2
  544. adjust_marks_del_3:
  545.     sub    si,ax            ;no - adjust it and store it back.
  546.     mov    [bx],si
  547. adjust_marks_del_2:
  548.     add    bx,2            ;go to the next mark.
  549.     loop    adjust_marks_del_1
  550.     ret
  551.  
  552.     assume    es:nothing
  553.  
  554.     public    get_syntax
  555. get_syntax:
  556. ;enter with al=character.
  557. ;don't change any other registers.
  558. ;exit with al=syntax of that character.
  559.     push    bx
  560.     mov    bx,ss:syntax_table
  561.     cmp    bx,NIL
  562.     je    get_syntax_3
  563.     push    ax
  564.     mov    ax,ss:[bx].name_length
  565.     lea    bx,[size form + bx]    ;make bx->name.
  566.     add    bx,ax            ;make bx->data.
  567.     pop    ax
  568.     xlat    ss:byte_ptr
  569.     pop    bx
  570.     ret
  571. get_syntax_3:
  572.     pop    bx
  573.     cmp    al,'_'
  574.     je    get_syntax_1
  575.     cmp    al,cr
  576.     je    get_syntax_2
  577.     cmp    al,lf
  578.     je    get_syntax_2
  579.     cmp    al,'0'
  580.     jb    get_syntax_0
  581.     cmp    al,'9'
  582.     jbe    get_syntax_1
  583.     cmp    al,'A'
  584.     jb    get_syntax_0
  585.     cmp    al,'Z'
  586.     jbe    get_syntax_1
  587.     cmp    al,'a'
  588.     jb    get_syntax_0
  589.     cmp    al,'z'
  590.     jbe    get_syntax_1
  591. get_syntax_0:
  592.     mov    al,0
  593.     ret
  594. get_syntax_1:
  595.     mov    al,1
  596.     ret
  597. get_syntax_2:
  598.     mov    al,2
  599.     ret
  600.  
  601.  
  602. code    ends
  603.  
  604.     end
  605.  
  606.